package com.seleniti.enpareja.android;

import java.io.IOException;
import java.net.CookieManager;
import java.net.CookieStore;

import org.ioc.commons.flowcontrol.activitymapper.IsActivityManager;
import org.ioc.commons.flowcontrol.messageboxfactory.MessageBoxFactory;
import org.ioc.commons.flowcontrol.placecontroller.HasPlaceData;
import org.ioc.commons.impl.android.common.util.SaveInstanceStateHelper;
import org.ioc.commons.impl.android.flowcontrol.activity.ShellActionBarActivity;
import org.ioc.commons.impl.android.flowcontrol.placecontroller.AndroidPlaceController;
import org.ioc.commons.impl.android.ui.HasEnabledWrapper;
import org.ioc.commons.impl.android.ui.HasPendingOperationsLoaderWrapper;
import org.ioc.commons.impl.android.ui.HasTextWrapper;
import org.ioc.commons.impl.android.ui.HasVisibilityWrapper;
import org.ioc.commons.ui.HasLoader;
import org.ioc.commons.ui.HasPendingOperationsLoader;
import org.ioc.commons.ui.HasText;
import org.ioc.commons.ui.HasValue;
import org.ioc.commons.ui.HasVisibility;
import org.ioc.commons.ui.IsWidget;
import org.ioc.commons.ui.impl.BaseAdapter;
import org.ioc.commons.ui.impl.HasLoaderAdapter;
import org.ioc.commons.ui.impl.HasValueAdapter;
import org.ioc.commons.ui.impl.HasVisibilityAdapter;
import org.ioc.commons.ui.impl.OnChangeCommand;
import org.ioc.commons.utils.Format;
import org.ioc.commons.utils.FormatterLogger;

import android.accounts.Account;
import android.accounts.AccountManager;
import android.accounts.AccountManagerFuture;
import android.accounts.AccountsException;
import android.accounts.AuthenticatorException;
import android.accounts.OperationCanceledException;
import android.content.Intent;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.text.Html;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnSystemUiVisibilityChangeListener;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.ScrollView;
import android.widget.Toast;

import com.gdevelop.gwt.syncrpc.LoginUtils;
import com.gdevelop.gwt.syncrpc.android.CookieManagerAvailableListener;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.seleniti.enpareja.android.control.controller.AndroidEnParejaAppControllerImpl;
import com.seleniti.enpareja.android.control.entrypoint.EnParejaAndroid;
import com.seleniti.enpareja.android.control.factory.ClientFactoryImpl;
import com.seleniti.enpareja.android.control.navigation.AppPlaceMapper;
import com.seleniti.enpareja.android.model.integration.gcm.GCMIntentService;
import com.seleniti.enpareja.android.ui.view.AppSettingsActivity.ResultCode;
import com.seleniti.enpareja.android.ui.widget.InfoInlineWidget;
import com.seleniti.enpareja.android.ui.widget.SliderPanelWidget;
import com.seleniti.enpareja.controller.common.domain.LoggedUserInfo;
import com.seleniti.enpareja.controller.control.place.EnParejaPlace;
import com.seleniti.enpareja.controller.model.integration.database.domain.CoupleType;
import com.seleniti.enpareja.controller.ui.main.AppShell;
import com.seleniti.enpareja.controller.ui.main.AppShell.Action;
import com.seleniti.enpareja.controller.ui.main.AppShell.Event;
import com.seleniti.enpareja.controller.ui.main.AppShell.Operation;
import com.seleniti.enpareja.controller.ui.main.AppShell.Presenter;
import com.seleniti.enpareja.controller.ui.main.AppShellPresenter;
import com.seleniti.enpareja.controller.ui.widget.SliderPanel;

public class AppShellActivity extends ShellActionBarActivity<Event, Operation, Action, Presenter> implements AppShell,
		IsActivityManager {

	public static String FORCE_REFRESH_KEY = "FORCE_REFRESH";

	private static final FormatterLogger logger = FormatterLogger.getLogger(AppShellActivity.class);

	private LinearLayout nonAssociatedPanel;
	private Menu menu;
	private Button btnDeleteNow;
	private SliderPanelWidget sliderPanel;
	private LinearLayout pendingRequestsToYouPanel;
	private LinearLayout pendingRequestsFromYouPanel;
	private LinearLayout rejectedRequestsFromYouPanel;
	private Button btnSwitchNow;
	private Button btnRetry;
	private InfoInlineWidget select2Info;

	private Button btnCoupleRequest;

	private Button btnGetCouple;

	private Button btnGetCouple2;

	private Button btnGetCouple3;

	private ProgressBar globalLoader;

	private Button btnLoadBasics;

	private ClientFactoryImpl clientFactory;

	private AndroidPlaceController placeController;

	private MessageBoxFactory messageBoxFactory;

	private AndroidEnParejaAppControllerImpl appController;

	private IsWidget display;

	private LinearLayout pnlFirstSteps;

	private Button btnSingleUser;

	private Button btnTryMe;

	private Button btnCoupleRequest2;

	private ScrollView scroll;

	public AppShellActivity() {
		this.presenter = new AppShellPresenter(this, eventbus, operationManager, actionController);
	}

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		this.clientFactory = ((EnParejaAndroid) this.getApplication()).getClientFactory();

		this.placeController = clientFactory.getPlaceController().forThisObject(this);
		this.messageBoxFactory = clientFactory.getMessageBoxFactory().forThisObject(this);
		this.appController = clientFactory.getAppController().forThisObject(AppShellActivity.this);

		getSupportActionBar().setDisplayShowHomeEnabled(false);
		setTitle("");
		setContentView(R.layout.app_shell);
		this.scroll = (ScrollView) findViewById(R.id.scroll);
		this.nonAssociatedPanel = (LinearLayout) findViewById(R.id.nonAssociatedPanel);
		this.pendingRequestsToYouPanel = (LinearLayout) findViewById(R.id.pendingRequestsToYouPanel);
		this.pendingRequestsFromYouPanel = (LinearLayout) findViewById(R.id.pendingRequestsFromYouPanel);
		this.rejectedRequestsFromYouPanel = (LinearLayout) findViewById(R.id.rejectedRequestsFromYouPanel);
		this.pnlFirstSteps = (LinearLayout) findViewById(R.id.pnlFirstSteps);
		this.btnDeleteNow = (Button) findViewById(R.id.btnDeleteNow);
		this.btnSwitchNow = (Button) findViewById(R.id.btnSwitchNow);
		this.btnRetry = (Button) findViewById(R.id.btnRetry);
		this.select2Info = (InfoInlineWidget) findViewById(R.id.select2Info);
		this.sliderPanel = (SliderPanelWidget) findViewById(R.id.sliderPanel);
		this.btnCoupleRequest = (Button) findViewById(R.id.btnCoupleRequest);

		this.btnCoupleRequest2 = (Button) findViewById(R.id.btnCoupleRequest2);
		this.btnSingleUser = (Button) findViewById(R.id.btnSingleUser);
		this.btnTryMe = (Button) findViewById(R.id.btnTryMe);

		this.btnCoupleRequest2.setText(Html.fromHtml(getString(R.string.get_couple_message)));
		this.btnSingleUser.setText(Html.fromHtml(getString(R.string.get_single_message)));
		this.btnTryMe.setText(Html.fromHtml(getString(R.string.get_try_message)));

		this.btnGetCouple = (Button) findViewById(R.id.btnGetCouple);
		this.btnGetCouple2 = (Button) findViewById(R.id.btnGetCouple2);
		this.btnGetCouple3 = (Button) findViewById(R.id.btnGetCouple3);
		this.btnLoadBasics = (Button) findViewById(R.id.btnLoadBasics);
		this.globalLoader = (ProgressBar) findViewById(R.id.globalLoader);
		// this.globalLoader.getIndeterminateDrawable().setColorFilter(Color.parseColor("#3397FD"),
		// android.graphics.PorterDuff.Mode.OVERLAY);
//		this.globalLoader.setOnSystemUiVisibilityChangeListener(new OnSystemUiVisibilityChangeListener() {
//			
//			@Override
//			public void onSystemUiVisibilityChange(int visibility) {
//				logger.info("Global loader visible? {0} Thread: {1}", visibility == View.VISIBLE, Thread.currentThread());
//			}
//		});

		OnClickListener goToCoupleRequestView = new OnClickListener() {

			@Override
			public void onClick(View v) {
				presenter.onGoToCoupleRequestsView();
			}
		};
		this.btnCoupleRequest.setOnClickListener(goToCoupleRequestView);
		this.btnCoupleRequest2.setOnClickListener(goToCoupleRequestView);
		this.btnSingleUser.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				makeSingle();
			}
		});
		this.btnTryMe.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				makeTestCouple();
			}
		});

		OnClickListener goToGetCoupleView = new OnClickListener() {

			@Override
			public void onClick(View v) {
				presenter.onGoToGetCoupleView();
			}
		};
		this.btnGetCouple.setOnClickListener(goToGetCoupleView);
		this.btnGetCouple2.setOnClickListener(goToGetCoupleView);
		this.btnGetCouple3.setOnClickListener(goToGetCoupleView);

		this.btnDeleteNow.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				presenter.onDeleteNow();
			}
		});

		this.btnSwitchNow.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				presenter.onSwitchElementsNow();
			}
		});

		this.btnLoadBasics.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				presenter.onLoadBasics();
			}
		});

		if (savedInstanceState != null) {
			SaveInstanceStateHelper ss = new SaveInstanceStateHelper(this.getClass().getName(), savedInstanceState);

			ss.restore()
					.visible(nonAssociatedPanelVisibility(), refreshButtonVisibility(), deleteButtonVisibility(),
							goBackButtonVisible(), firstStepsVisibility()).loader(globalLoader());
		}

		this.btnRetry.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View v) {
				appController.reload();
			}
		});

		clientFactory.setAppShell(this);

		appController.run(null);

		GCMIntentService.registerAtGCM(this);
	}

	@Override
	public void setDisplay(IsWidget display) {
		this.display = display;
	}

	@Override
	public IsWidget getDisplay() {
		return this.display;
	}

	@Override
	protected void onResume() {
		super.onResume();

		int googlePlayServicesAvailable = GooglePlayServicesUtil.isGooglePlayServicesAvailable(this);
		if (googlePlayServicesAvailable != ConnectionResult.SUCCESS) {
			GooglePlayServicesUtil.getErrorDialog(googlePlayServicesAvailable, this,
					AppPlaceMapper.REQUEST_CODE_GET_GOOGLE_PLAY_SERVICE);
		}

		boolean redirected = false;
		if (this.getIntent() != null) {
			int placeNo = this.getIntent().getIntExtra(AndroidPlaceController.PLACE_KEY, -1);
			if (placeNo >= 0) {
				this.getIntent().removeExtra(AndroidPlaceController.PLACE_KEY);
				EnParejaPlace place = EnParejaPlace.values()[placeNo];
				this.placeController.goTo(place);

				redirected = true;
			}

			if (this.getIntent().getBooleanExtra(FORCE_REFRESH_KEY, false)) {
				this.getIntent().putExtra(FORCE_REFRESH_KEY, false);

				this.actionController.invokeAction(Action.RefreshNow);
			}
		}

		if (!redirected) {
			placeController.handleCurrentPlace();
		}
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);
		switch (requestCode) {
		case AppPlaceMapper.REQUEST_CODE_EMAIL:
			if (resultCode == RESULT_OK) {
				Account loggedAccount = (Account) data.getExtras().get(LoginUtils.ACCOUNT_KEY);
				final AccountManager manager = (AccountManager) getSystemService(ACCOUNT_SERVICE);

				if (loggedAccount == null) {

					String accountName = data.getStringExtra(AccountManager.KEY_ACCOUNT_NAME);

					Account[] accounts = manager.getAccountsByType("com.google");
					for (final Account account : accounts) {
						if (account.name.equals(accountName)) {
							loggedAccount = account;

							break;
						}
					}
				}

				final CookieManagerAvailableListener listener = new CookieManagerAvailableListener() {

					@Override
					public void onCMAvailable(CookieManager arg0) {
						CookieStore cookieStore = arg0.getCookieStore();
						logger.info("Cookies post login {0}", cookieStore != null ? cookieStore.getCookies()
								: "-- no cookies sent --");
						clientFactory.setCookieManager(arg0);

						clientFactory.getLoginController().refreshLoggedUserInfo();
						placeController.goTo(EnParejaPlace.Main);
					}

					@Override
					public void onAuthFailure() {
						presenter.onAuthFailure();
					}
				};
				final Account useAccount = loggedAccount;
				new AsyncTask<Void, Void, Void>() {

					@Override
					protected Void doInBackground(Void... params) {
						try {
							String token = buildToken(manager, useAccount);
							manager.invalidateAuthToken(useAccount.type, token);
							token = buildToken(manager, useAccount);

							LoginUtils.setLoginUrl(ClientFactoryImpl.getWebsiteUrl());

							LoginUtils.loginAppEngine(AppShellActivity.this, listener, useAccount);
						} catch (IOException | AccountsException e) {
							logger.error(e);
							presenter.onAuthFailure();
						}

						return null;
					}
				}.execute();
			} else {
				this.messageBoxFactory.error("Login fallido", "No se pudo logar utilizando la cuenta de google");
			}
			break;
		// case AppPlaceMapper.REQUEST_CODE_GAE_USER_LOGGED_IN:
		// break;
		case AppPlaceMapper.CHECK_FOR_RESET_REQUIRED:
			ResultCode rc = resultCode >= 0 && resultCode < ResultCode.values().length ? ResultCode.values()[resultCode]
					: null;

			if (rc == ResultCode.ACTIVITY_REQUIRES_RESET) {
				Toast.makeText(this,
						// "You must exit from the application and enter again to apply some performed changes",
						"Debes salir y volver a entrar en la aplicación para que los cambios surjan efecto",
						Toast.LENGTH_LONG).show();
			}

			break;
		}
	}

	private String buildToken(AccountManager manager, Account account) throws OperationCanceledException,
			AuthenticatorException, IOException {
		AccountManagerFuture<Bundle> future = manager.getAuthToken(account, "ah", null, false, null, null); // ah
																											// is
																											// app
																											// engine
		Bundle token = future.getResult();
		return token.get(AccountManager.KEY_AUTHTOKEN).toString();
	}

	@Override
	protected void onSaveInstanceState(Bundle outState) {
		super.onSaveInstanceState(outState);
		SaveInstanceStateHelper ss = new SaveInstanceStateHelper(this.getClass().getName(), outState);

		ss.save()
				.visible(nonAssociatedPanelVisibility(), refreshButtonVisibility(), deleteButtonVisibility(),
						goBackButtonVisible(), firstStepsVisibility()).loader(globalLoader())
				.visible(loadBasicsButtonVisibility()).text(loadBasicsButtonText());
	}

	@Override
	protected void onRestoreInstanceState(Bundle savedInstanceState) {
		super.onRestoreInstanceState(savedInstanceState);

		SaveInstanceStateHelper ss = new SaveInstanceStateHelper(this.getClass().getName(), savedInstanceState);

		ss.restore()
				.visible(nonAssociatedPanelVisibility(), refreshButtonVisibility(), deleteButtonVisibility(),
						goBackButtonVisible(), firstStepsVisibility()).loader(globalLoader())
				.visible(loadBasicsButtonVisibility()).text(loadBasicsButtonText());
	}

	@Override
	public HasValue<LoggedUserInfo> loggedUserInfo() {
		return HasValueAdapter.<LoggedUserInfo> forField("loggerUserInfo", this).onChange(
				new OnChangeCommand<LoggedUserInfo>() {

					@Override
					public void execute(LoggedUserInfo value) {
						refreshMenuFromLUI(value);

						invalidateOptionsMenu();
					}
				});
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		getMenuInflater().inflate(R.menu.main, menu);
		this.menu = menu;

		LoggedUserInfo lui = loggedUserInfo().getValue();

		refreshMenuFromLUI(lui);

		return true;
	}

	private void refreshMenuFromLUI(LoggedUserInfo lui) {
		String headerText = lui != null && lui.getUserName() != null ? Format.capitalize(lui.getUserName())
				+ (lui.getCoupleName() != null ? (lui.getCoupleType() == null
						|| lui.getCoupleType() == CoupleType.USERS_COUPLE ? " y "
						+ (Format.capitalize(lui.getCoupleName())) : "") : "") : "";
		getSupportActionBar().setTitle(headerText);
		if (menu != null) {
			MenuItem logout = menu.findItem(R.id.logout);
			MenuItem admin = menu.findItem(R.id.action_admin);

			if (logout != null) {
				logout.setVisible(lui != null && lui.isLogged());
			}
			if (admin != null) {
				admin.setVisible(lui != null && lui.isLogged() && lui.isAdmin());
			}
		}
	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		// Handle action bar item clicks here. The action bar will
		// automatically handle clicks on the Home/Up button, so long
		// as you specify a parent activity in AndroidManifest.xml.
		int id = item.getItemId();
		switch (id) {
		case R.id.user_settings:
			presenter.onOpenUserSettings();
			return true;
		case R.id.app_settings:
			presenter.onOpenAppSettings();
			return true;
		case R.id.logout:
			presenter.onLogout();
			return true;
		case R.id.visit_website:
			presenter.onOpenWebSiteVersion();
			return true;
		case R.id.exit:
			finish();
			Intent intent = new Intent(Intent.ACTION_MAIN);
			intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
			intent.addCategory(Intent.CATEGORY_HOME);
			startActivity(intent);
			break;
		}

		return super.onOptionsItemSelected(item);
	}

	@Override
	public void openLink(String url, boolean asExternal) {
		Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
		startActivity(browserIntent);
	}

	@Override
	public void openSettings() {
		this.presenter.onOpenUserSettings();
	}

	@Override
	public void openAdminConsole() {
		this.presenter.onOpenAdminConsole();
	}

	@Override
	public HasVisibility goBackButtonVisible() {
		/*
		 * Handled automatically by android
		 */
		return HasVisibilityAdapter.forField("dummyGoBackButtonVisible", this);
	}

	@Override
	public void logout() {
		this.presenter.onLogout();
	}

	@Override
	public void openSelenitiWebSite() {
		this.openLink("http://www.seleniti.com", true);
	}

	@Override
	public HasPendingOperationsLoader globalLoader() {
		return HasPendingOperationsLoaderWrapper.fromVisible(globalLoader, this);
	}

	@Override
	public SliderPanel mainContainer() {
		return this.sliderPanel;
	}

	@Override
	public HasVisibility gettingStartedInfoVisible() {
		// TODO Cambiar
		return HasVisibilityAdapter.forField("firstVisitInfoVisible", this);
	}

	@Override
	public void onBackPressed() {

		boolean gone = presenter.onGoBackPressed();

		if (!gone) {
			super.onBackPressed();

			HasPlaceData cpd = placeController.getCurrentPlaceData();

			placeController.notifyPlaceChanged();

			if (cpd == null
					|| (cpd.getPlaceId() == EnParejaPlace.Main && !clientFactory.getLoginController().isLogged())) {
				finish();
			}
		}
	}

	@Override
	public void goToMarketPlace() {
		final String appPackageName = this.getPackageName(); // getPackageName()

		try {
			this.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + appPackageName)));
		} catch (android.content.ActivityNotFoundException anfe) {
			this.startActivity(new Intent(Intent.ACTION_VIEW, Uri
					.parse("https://play.google.com/store/apps/details?id=" + appPackageName)));
		}
	}

	@Override
	public void refreshNow() {
		this.presenter.onRefreshNow();
	}

	@Override
	public void makeSingle() {
		this.presenter.onMakeSingle();
	}

	@Override
	public void makeTestCouple() {
		this.presenter.onMakeTestCouple();
	}

	@Override
	public HasLoader makingCoupleIndicator() {
		return HasLoaderAdapter.forField("makingCoupleIndicator", this).onChange(new OnChangeCommand<Boolean>() {

			@Override
			public void execute(Boolean value) {
				HasEnabledWrapper.setEnabled(!value, btnCoupleRequest, btnSingleUser, btnTryMe);
			}
		});
	}

	@Override
	public HasVisibility firstStepsVisibility() {
		return HasVisibilityWrapper.from(this.pnlFirstSteps, this);
	}

	@Override
	public HasVisibility nonAssociatedButtonVisibility() {
		return HasVisibilityWrapper.from(this.btnCoupleRequest, this);
	}

	@Override
	public HasVisibility nonAssociatedPanelVisibility() {
		return HasVisibilityWrapper.from(nonAssociatedPanel, this);
	}

	@Override
	public HasVisibility refreshButtonVisibility() {
		return HasVisibilityAdapter.forField("refreshButtonVisibility", this)
		/**
		 * Not shown in Android app
		 */
		// .onChange(new OnChangeCommand<Boolean>() {
		//
		// @Override
		// public void execute(Boolean value) {
		// MenuItem item = menu.findItem(R.id.btnRefresh);
		// item.setVisible(Boolean.TRUE.equals(value));
		// invalidateOptionsMenu();
		// }
		// })
		;
	}

	@Override
	public HasVisibility requestsToYouPanelVisibility() {
		return HasVisibilityWrapper.from(this.pendingRequestsToYouPanel, this);
	}

	@Override
	public HasVisibility pendingRequestsFromYouPanelVisibility() {
		return HasVisibilityWrapper.from(this.pendingRequestsFromYouPanel, this);
	}

	@Override
	public HasVisibility rejectedRequestsFromYouPanelVisibility() {
		return HasVisibilityWrapper.from(this.rejectedRequestsFromYouPanel, this);
	}

	@Override
	public HasVisibility retryButtonVisibility() {
		return HasVisibilityAdapter.forField("retryButtonVisibility", this, btnRetry.getVisibility() == View.VISIBLE)
				.onChange(new OnChangeCommand<Boolean>() {

					@Override
					public void execute(Boolean value) {
						btnRetry.setVisibility(value ? View.VISIBLE : View.GONE);
						refreshMarginBottom();
					}
				});
	}

	@Override
	public HasVisibility deleteButtonVisibility() {
		return HasVisibilityAdapter.forField("deleteButtonVisibility", this,
				btnDeleteNow.getVisibility() == View.VISIBLE).onChange(new OnChangeCommand<Boolean>() {

			@Override
			public void execute(Boolean value) {
				btnDeleteNow.setVisibility(value ? View.VISIBLE : View.GONE);
				refreshMarginBottom();
			}
		});
	}

	@Override
	public HasVisibility switchButtonVisibility() {
		return HasVisibilityAdapter.forField("switchButtonVisibility", this,
				btnSwitchNow.getVisibility() == View.VISIBLE).onChange(new OnChangeCommand<Boolean>() {

			@Override
			public void execute(Boolean value) {
				btnSwitchNow.setVisibility(value ? View.VISIBLE : View.GONE);
				refreshMarginBottom();
			}
		});
	}

	@Override
	public HasVisibility select2InfoVisibility() {
		return HasVisibilityAdapter
				.forField("select2InfoVisibility", this, select2Info.getVisibility() == View.VISIBLE).onChange(
						new OnChangeCommand<Boolean>() {

							@Override
							public void execute(Boolean value) {
								select2Info.setVisibility(value ? View.VISIBLE : View.GONE);
								refreshMarginBottom();
							}
						});
	}

	@Override
	public HasVisibility loadBasicsButtonVisibility() {
		return HasVisibilityAdapter.forField("loadBasicsButtonVisibility", this,
				btnLoadBasics.getVisibility() == View.VISIBLE).onChange(new OnChangeCommand<Boolean>() {

			@Override
			public void execute(Boolean value) {
				btnLoadBasics.setVisibility(value ? View.VISIBLE : View.GONE);
				refreshMarginBottom();
			}
		});
	}

	@Override
	public HasText loadBasicsButtonText() {
		return HasTextWrapper.from(btnLoadBasics, this);
	}

	private void refreshMarginBottom() {
		boolean margin = btnRetry.getVisibility() == View.VISIBLE || btnDeleteNow.getVisibility() == View.VISIBLE
				|| btnSwitchNow.getVisibility() == View.VISIBLE || select2Info.getVisibility() == View.VISIBLE
				|| btnLoadBasics.getVisibility() == View.VISIBLE;

		RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(
				RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);

		layoutParams.setMargins(0, 0, 0, margin ? 35 : 0);

		this.scroll.setLayoutParams(layoutParams);
	}

	@Override
	public void onDestroy() {
		super.onDestroy();

		BaseAdapter.cleanAdapters(this);
	}
}
